<template>
  <el-row class="p-5 pt-0" @keyup.enter="getRoleData">

    <el-col v-if="showSearch">
      <el-form ref="searchForm" :inline="true" :model="search" class="demo-form-inline">
        <el-form-item label="角色名称" class="font-black">
          <el-input v-model="search.roleName" :disabled="loading" :size="store.layoutSize" clearable
                    style="width: 150px"
                    placeholder="请输入角色名称"/>
        </el-form-item>
        <el-form-item label="权限字符" class="font-black">
          <el-input v-model="search.roleKey" :disabled="loading" :size="store.layoutSize" clearable style="width: 150px"
                    placeholder="请输入权限字符"/>
        </el-form-item>
        <el-form-item label="状态" class="font-black">
          <el-select v-model="search.status" :disabled="loading" :size="store.layoutSize" clearable style="width: 150px"
                     placeholder="角色状态" @change="getRoleData">
            <el-option v-for="item in statusData.data" :label="item.dictLabel" :value="item.dictValue"/>
          </el-select>
        </el-form-item>
        <el-form-item label="创建时间" class="font-black">
          <el-date-picker v-model="date"
                          :disabled="loading"
                          :shortcuts="shortcuts"
                          :size="store.layoutSize"
                          clearable
                          end-placeholder="结束日期"
                          range-separator="-"
                          start-placeholder="开始日期"
                          style="width: 210px"
                          type="daterange"
                          unlink-panels
                          value-format="YYYY-MM-DD"
                          @change="getRoleData"
          />
        </el-form-item>
        <el-form-item>
          <el-button :color="store.getTheme" :disabled="loading" :size="store.layoutSize" auto-insert-space
                     @click="getRoleData">
            <template #icon>
              <el-icon>
                <Search/>
              </el-icon>
            </template>
            查询
          </el-button>
          <el-button :color="store.getTheme" :disabled="loading" :size="store.layoutSize" auto-insert-space plain
                     @click="clearSearch">
            <template #icon>
              <el-icon>
                <Refresh/>
              </el-icon>
            </template>
            重置
          </el-button>
        </el-form-item>
      </el-form>
    </el-col>

    <el-col class="flex justify-between">
      <div>
        <el-button :color="store.getTheme" :disabled="loading" :size="store.layoutSize" auto-insert-space plain
                   type="primary"
                   @click="add">
          <template #icon>
            <el-icon>
              <Plus/>
            </el-icon>
          </template>
          新增
        </el-button>
        <el-button :disabled="delDisabled || loading" :size="store.layoutSize" auto-insert-space plain type="danger"
                   @click="delSelect">
          <template #icon>
            <el-icon>
              <Delete/>
            </el-icon>
          </template>
          删除
        </el-button>
        <el-button :disabled="search.total === 0 || loading" :size="store.layoutSize" auto-insert-space plain
                   type="warning"
                   @click="download">
          <template #icon>
            <el-icon>
              <Download/>
            </el-icon>
          </template>
          导出
        </el-button>
      </div>
      <div>
        <el-tooltip
            class="box-item"
            effect="dark"
            :content="showSearch?'隐藏搜索':'显示搜索'"
            placement="top"
        >
          <el-button :color="store.getTheme" :size="store.layoutSize" @click="showSearch = !showSearch" circle>
            <el-icon>
              <Search/>
            </el-icon>
          </el-button>
        </el-tooltip>
        <el-tooltip
            class="box-item"
            effect="dark"
            content="刷新"
            placement="top"
        >
          <el-button :color="store.getTheme" :disabled="loading" :size="store.layoutSize" circle @click="getRoleData">
            <el-icon>
              <Refresh/>
            </el-icon>
          </el-button>
        </el-tooltip>
      </div>
    </el-col>

    <el-col class="mt-2">
      <el-table :size="store.layoutSize" v-loading="loading" element-loading-text="正在努力加载中..."
                :data="roleTableData.data"
                style="width: 100%" table-layout="auto" row-key="id" @selection-change="handleSelectionChange"
                highlight-current-row empty-text="无数据">

        <el-table-column align="center" reserve-selection="true" type="selection" :color="store.getTheme"
                         width="55"/>

        <el-table-column align="center" label="角色编号" width="80" prop="roleId"/>

        <el-table-column align="center" label="角色名称" prop="roleName"/>

        <el-table-column align="center" label="权限字符" prop="roleKey"/>

        <el-table-column align="center" label="显示顺序" prop="roleSort"/>

        <el-table-column align="center" label="状态">
          <template #default="scope">
            <el-switch @change="changeStatus(scope.row,$event)"
                       :active-color="store.getTheme"
                       v-model="scope.row.status" active-value="0"
                       inactive-value="1"/>
          </template>
        </el-table-column>

        <el-table-column align="center" label="创建时间" width="180">
          <template #default="scope">
            {{ moment(scope.row.createTime).format('YYYY-MM-DD HH:mm:ss') }}
          </template>
        </el-table-column>

        <el-table-column align="center" label="操作">
          <template #default="scope">
            <el-link :underline="false" class="text-xs" :style="{color: store.getTheme}"
                     @click="update(scope.row)">
              <el-icon>
                <EditPen/>
              </el-icon>
              修改
            </el-link>
            <el-link :underline="false" class="text-xs ml-3" :style="{color: store.getTheme}"
                     v-if="scope.row.parentId !== 0" @click="del(scope.row)">
              <el-icon>
                <Delete/>
              </el-icon>
              删除
            </el-link>
            <el-link :underline="false" class="text-xs ml-3" :style="{color: store.getTheme}">
              <el-icon>
                <DArrowRight/>
              </el-icon>
              更多
            </el-link>
          </template>
        </el-table-column>
      </el-table>
    </el-col>
    <el-col class="mt-3 flex justify-end">
      <el-pagination
          :small="store.layoutSize === 'small'"
          :default-current-page="search.pageNum"
          :currentPage="search.pageNum"
          :page-size='search.pageSize'
          :page-sizes="[10, 20, 50, 100]"
          :pager-count="5"
          layout="total, sizes, prev, pager, next, jumper"
          :total="search.total"
          @size-change="handlePageSizeChange"
          @current-change="handleCurrentPageChange"
      />
    </el-col>

    <!-- 添加或修改角色配置对话框 -->
    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
        <el-form-item label="角色名称" prop="roleName">
          <el-input v-model="form.roleName" placeholder="请输入角色名称"/>
        </el-form-item>
        <el-form-item label="权限字符" prop="roleKey">
          <el-input v-model="form.roleKey" placeholder="请输入权限字符"/>
        </el-form-item>
        <el-form-item label="角色顺序" prop="roleSort">
          <el-input-number v-model="form.roleSort" controls-position="right" :min="0"/>
        </el-form-item>
        <el-form-item label="状态">
          <el-radio-group v-model="form.status">
            <el-radio
                v-for="dict in statusData.data"
                :key="dict.dictCode"
                :label="dict.dictValue"
            >{{ dict.dictLabel }}
            </el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="菜单权限">
          <el-checkbox v-model="expandAll" @change="expand">展开/折叠</el-checkbox>
          <el-checkbox v-model="menuNodeAll" @change="handleNodeAll">全选/全不选
          </el-checkbox>
          <el-checkbox v-model="form.menuCheckStrictly">父子联动
          </el-checkbox>
          <el-tree
              v-if="refreshTable"
              style="width: 100%"
              class="border"
              :data="menuData.data"
              :default-expand-all="expandAll"
              :default-checked-keys="form.menuIds"
              show-checkbox
              ref="menuRef"
              node-key="menuId"
              :check-strictly="!form.menuCheckStrictly"
              empty-text="加载中，请稍候"
              :props="{label:'menuName'}"></el-tree>
        </el-form-item>
        <el-form-item label="备注">
          <el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="flex justify-end">
        <el-button type="primary" :loading="buttonLoading" @click="submitForm(formRef)">
          <span v-if="!buttonLoading">保 存</span>
          <span v-else>保存中...</span>
        </el-button>
        <el-button @click="open = false">取 消</el-button>
      </div>
    </el-dialog>

  </el-row>
</template>

<script setup lang="ts">
import {useStore} from "@/store";
import {nextTick, reactive, ref} from "vue";
import {getDictData} from "@/api/dictData";
import moment from "moment";
import {delRole, downloadRole, getRoleDataByParams, saveRoleWithMenus} from "@/api/role";
import {ElMessageBox, ElNotification, FormInstance, FormRules} from "element-plus";
import {getMenuDataByParams, getMenuIdsByRoleId} from "@/api/menu";
//引入store
const store = useStore()

//弹出层
const open = ref(false)
const title = ref('')

//定义表格加载状态
const loading = ref(false)

//定义搜索框显示状态
const showSearch = ref(true)

//定义时间区间
const date = ref([])

//定义删除按钮禁用
const delDisabled = ref(true)

const formRef = ref<FormInstance>()

//赋值状态信息
const statusData = reactive({
  data: []
})
getDictData({'dictType': 'sys_normal_disable'}).then(result => {
  statusData.data = result.data.data
})

//控制全选
const menuNodeAll = ref(false)
const menuRef = ref()

function handleNodeAll() {
  if (menuNodeAll.value) {
    form.menuIds = []
    menuData.data.forEach(item => {
      form.menuIds.push(item.menuId)
    })
  } else {
    form.menuIds = []
  }
  menuRef.value.setCheckedKeys(form.menuIds)
}

//获取菜单数据
const menuData = reactive({
  data: []
})

//获取菜单数据
function getMenuData() {
  getMenuDataByParams(search).then(result => {
    menuData.data = result.data.data
  })
}

//展开树状图
const expandAll = ref(false)
const refreshTable = ref(true)

function expand() {
  refreshTable.value = false
  nextTick(() => {
    refreshTable.value = true
  })
}

//搜索表单
const search = reactive({
  pageNum: 1,
  pageSize: 10,
  total: 0,
  roleName: null,
  roleKey: null,
  status: null,
  startDate: null,
  endDate: null
})

//清空搜索表单
function clearSearch() {
  search.roleName = null
  search.roleKey = null
  search.status = null
  date.value = []
  getRoleData()
}

//获取角色表格信息
const roleTableData = reactive({
  data: []
})
getRoleData()

function getRoleData() {
  loading.value = true
  if (date.value && date.value.length > 0) {
    search.startDate = date.value[0]
    search.endDate = date.value[1]
  } else {
    search.startDate = null
    search.endDate = null
  }
  getRoleDataByParams(search).then(result => {
    search.total = result.data.data.total
    roleTableData.data = result.data.data.list
    loading.value = false
  })
}

//定义新增、修改表单
const form = reactive({
  roleId: null,
  roleName: null,
  roleKey: null,
  roleSort: 0,
  status: "0",
  menuIds: [],
  deptIds: [],
  menuCheckStrictly: true,
  deptCheckStrictly: true,
  remark: null,
  createBy: null,
  updateBy: null,
})

//清空表单
function clearForm() {
  form.roleId = null
  form.roleName = null
  form.roleKey = null
  form.roleSort = 0
  form.status = "0"
  form.menuIds = []
  form.deptIds = []
  form.menuCheckStrictly = true
  form.deptCheckStrictly = true
  form.remark = null
  form.createBy = null
  form.updateBy = null
}

//新增角色
function add() {
  clearForm()
  getMenuData()
  form.createBy = store.getUser.userName
  title.value = '添加角色'
  open.value = true
}

//修改角色
function update(val) {
  clearForm()
  getMenuData()
  form.updateBy = store.getUser.userName
  form.roleId = val.roleId
  form.roleName = val.roleName
  form.roleKey = val.roleKey
  form.roleSort = val.roleSort
  form.status = val.status
  form.remark = val.remark
  form.menuCheckStrictly = val.menuCheckStrictly
  form.deptCheckStrictly = val.deptCheckStrictly
  getMenuIdsByRoleId({roleId: val.roleId}).then(result => {
    form.menuIds = result.data.data
    title.value = '修改角色'
    open.value = true
  })
}

//删除角色
function del(val) {
  ElMessageBox.confirm('您确定要删除<' + val.roleName + '>角色吗？', '警告', {
    confirmButtonText: '删除',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    delRole({roleId: val.roleId}).then(result => {
      if (result.data.code === 200) {
        ElNotification({
          message: result.data.msg,
          type: 'success'
        })
      }
      getRoleData()
    })
  })
}

//定义选中的行
const multipleSelection = ref<[]>([])
const handleSelectionChange = (val: []) => {
  const arr = []
  val.filter(item => {
    arr.push(item.roleId)
  })
  multipleSelection.value = arr
  if (multipleSelection.value.length > 0) {
    delDisabled.value = false
  } else {
    delDisabled.value = true
  }
}

//批量删除角色
function delSelect() {
  ElMessageBox.confirm('您确定要删除编号为[' + multipleSelection.value + ']角色吗？', '警告', {
    confirmButtonText: '删除',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    delRole({roleIds: multipleSelection.value}).then(result => {
      if (result.data.code === 200) {
        ElNotification({
          message: result.data.msg,
          type: 'success'
        })
      }
      getRoleData()
    })
  })
}

//表格中状态切换开关
function changeStatus(row, val) {
  ElMessageBox.confirm('确定要' + (val === '0' ? '启用' : '停用') + '<' + row.roleName + '>角色吗？', '系统提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    console.log(row.roleId)
    console.log(val)
  }).catch(() => {
    if (val === '0') {
      row.status = '1';
    } else {
      row.status = '0';
    }

  })
}

//控制分页
function handleCurrentPageChange(val) {
  search.pageNum = val;
  getRoleData()
}

//控制页大小
function handlePageSizeChange(val) {
  search.pageSize = val;
  getRoleData()
};

//时间选择器快捷选择
const shortcuts = [
  {
    text: '上周内',
    value: () => {
      const end = new Date()
      const start = new Date()
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
      return [start, end]
    },
  },
  {
    text: '近一个月',
    value: () => {
      const end = new Date()
      const start = new Date()
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
      return [start, end]
    },
  },
  {
    text: '近三个月',
    value: () => {
      const end = new Date()
      const start = new Date()
      start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
      return [start, end]
    },
  },
]

// 表单校验
const rules = reactive<FormRules>({
  roleName: [
    {required: true, message: "角色名称不能为空", trigger: "blur"}
  ],
  roleKey: [
    {required: true, message: "权限字符不能为空", trigger: "blur"}
  ],
  roleSort: [
    {required: true, message: "角色顺序不能为空", trigger: "blur"}
  ]
})

//按钮加载状态
const buttonLoading = ref(false)

//提交新增、修改表单
const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate((valid) => {
    if (valid) {
      buttonLoading.value = true
      let arr = menuRef.value.getCheckedKeys()
      menuRef.value.getHalfCheckedKeys().forEach(key => {
        arr.push(key)
      })
      form.menuIds = arr
      saveRoleWithMenus(form).then(result => {
        if (result.data.code === 200) {
          ElNotification({
            message: result.data.msg,
            type: 'success'
          })
          open.value = false
        }
        getRoleData()
        buttonLoading.value = false
      })
    }
  })
}

//导出数据
function download() {
  ElMessageBox.confirm('您确定要导出<' + search.total + '>条数据吗？', '警告', {
    confirmButtonText: '导出',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    downloadRole(search).then(response => {
      let disposition = response.headers['content-disposition'];
      //以下部分有需要优化，如后端返回时没有携带文件后缀名,没有.时会有问题等等
      let filename = disposition ? disposition.substring(disposition.indexOf('=') + 1, disposition.indexOf('.')) : "下载文件";
      let newName = decodeURI(escape(filename))
      let extName = disposition.substring(disposition.indexOf('.') + 1)
      let blob = new Blob([response.data], {type: 'application/vnd.ms-excel'});
      let link = document.createElement("a");
      let evt = document.createEvent("HTMLEvents");
      evt.initEvent("click", false, false);
      link.href = URL.createObjectURL(blob);
      link.download = newName + "." + extName;
      link.style.display = "none";
      document.body.appendChild(link);
      link.click();
      window.URL.revokeObjectURL(link.href);
    })
  })
}
</script>

<style scoped>

</style>
